//
//  CSRouteSelectView.swift
//  Cycling
//
//  Created by CSS on 4/1/23.
//

import UIKit

import MBProgressHUD

import MapboxNavigation
import MapboxDirections
import MapboxCoreNavigation

class CSRouteSelectView: UIView {
    
    private var routeIsLoading = true
    
    lazy private var tableView: UITableView = {
        let tableView: UITableView = .forAutoLayout()
        
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.dataSource = self
        
        return tableView
    }()
    
    // MARK: 中间变量
    private var routeOptions: NavigationRouteOptions?
    private var routeResponse: RouteResponse?
    private var routes: [Route] = []
    
    // MARK: 外部设置类
    public var goNavigationBlock:((IndexedRouteResponse, RouteOptions?) -> Void)?
    public var willChangeRoutesBlock:(([Route]?, Route?) -> Void)?
    public var requestFailedRoutes:(() -> Void)?

    override var intrinsicContentSize: CGSize {
        let rowNums: CGFloat = max(2, .init(routes.count))
        return .init(width: 320, height: rowNums * type(of: self).routeHeight)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setup()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setup() {
        
        addSubview(tableView)
        tableView.pinTo(parentView: self)
        tableView.registerDefaultNibCell(withSingleClass: CSRouteSelectCell.self)
        tableView.rowHeight = CSRouteSelectView.routeHeight
        tableView.estimatedRowHeight = tableView.rowHeight
        
        backgroundColor = .white
    }
    
}

// MARK: UITableView处理类
extension CSRouteSelectView: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        routes.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CSRouteSelectCell = .reuseCell(forTableView: tableView)
        if routes.count > indexPath.row {
            cell.route = routes[indexPath.row]
        }
        cell.routeIndex = indexPath.row
        cell.goNavigationBlock = { [weak self] in
            guard let self = self else {
                return
            }
            guard let routeResponse = self.routeResponse else {
                return
            }
            self.goNavigationBlock?(IndexedRouteResponse(routeResponse: routeResponse, routeIndex: $0), self.routeOptions)
        }
        return cell
    }
    
}

// MARK: 对外访问方法
extension CSRouteSelectView {
    
    public static let routeHeight: CGFloat = 65
    
    public func reload(withStartPoint point: CLLocationCoordinate2D, toPoint: CLLocationCoordinate2D) {
        
        requestRoutesData(withStartPoint: point, toPoint: toPoint)
    }
    
}

// MARK: 工具类方法(UI刷新)
private extension CSRouteSelectView {
    
    func reloadTableData() {
        tableView.reloadData()
    }
    
    func animateRefreshSelectView() {
        invalidateIntrinsicContentSize()
        superview?.setNeedsLayout()
        UIView.animate(withDuration: 0.25) {
            self.superview?.layoutIfNeeded()
        }
    }
    
}


// MARK: 工具类方法(数据处理类)
private extension CSRouteSelectView {
    
    func requestRoutesData(withStartPoint point: CLLocationCoordinate2D, toPoint: CLLocationCoordinate2D) {
        MBProgressHUD.showAdded(to: self, animated: true)
        
        let origin = Waypoint(coordinate: point)
        let destination = Waypoint(coordinate: toPoint)
        
        DispatchQueue.global().async { [weak self] in
            guard let self = self else {
                return
            }
            
            let routeOptions = NavigationRouteOptions(waypoints: [origin, destination], profileIdentifier: .cycling)
            routeOptions.includesSpokenInstructions = true
            routeOptions.locale = .current
            self.routeOptions = routeOptions
            
            Directions.shared.calculate(routeOptions) { session, result in
                switch result {
                case .failure(let error):
                    print(error.localizedDescription)
                    self.emptyDataAndReloadUI()
                case .success(let response):
                    // Pass the first generated route to the the NavigationViewController
                    guard let routes = response.routes, routes.count > 0 else {
                        self.emptyDataAndReloadUI()
                        return
                    }
                    self.routeResponse = response
                    self.routes = routes
                    self.willChangeRoutesBlock?(routes, routes[0])
                    routes.forEach({ $0.speechLocale = .current })
                    DispatchQueue.main.async {
                        self.reloadTableData()
                        MBProgressHUD.hide(for: self, animated: true)
                        self.animateRefreshSelectView()
                    }
                }
            }
        }
    }
    
    func emptyDataAndReloadUI() {
        routeResponse = nil
        routes.removeAll()
        DispatchQueue.main.async { [weak self] in
            guard let self = self else {
                return
            }
            self.reloadTableData()
            MBProgressHUD.hide(for: self, animated: true)
            self.animateRefreshSelectView()
            self.willChangeRoutesBlock?(nil, nil)
            self.requestFailedRoutes?()
        }
    }
    
}
